/*
Package app
*/
package goboot

import (
	"github.com/spf13/viper"
	"go.uber.org/dig"
	"log"
	"os"
	"os/signal"
	"syscall"
)

type GobootApp interface {
	GetContainer() *dig.Container
	GetViper() *viper.Viper
	SetViper(vp *viper.Viper)
	WaitShutdownSignal()
	RegisterShutdownFn(fn func())
	Shutdown()
}

type GobootAppOption func(app GobootApp)

// New 构造一个新的程序
func New(options ...GobootAppOption) GobootApp {
	// 新生成一个app
	app := &DefaultGobootApp{
		shutdown:  make(chan bool),
		container: dig.New(),
		shutdownFns: make([]func(),0),
	}
	// 配置
	for _,option := range options{
		option(app)
	}
	return app
}

type DefaultGobootApp struct {
	container  *dig.Container // 容器
	vp *viper.Viper // 配置
	shutdownFns []func()
	shutdown   chan bool // shutdown
}

// GetContainer 获取容器
func (app *DefaultGobootApp) GetContainer() *dig.Container {
	return app.container
}

func (app *DefaultGobootApp) GetViper() *viper.Viper {
	return app.vp
}

func (app *DefaultGobootApp) SetViper(vp *viper.Viper){
	app.vp = vp
}

func (app *DefaultGobootApp) WaitShutdownSignal() {
	sign := make(chan os.Signal, 1)
	signal.Notify(sign, syscall.SIGINT)
	go func() {
		sig := <-sign
		log.Println("receive shutdown signal", sig)
		close(app.shutdown)
	}()
	<-app.shutdown
}

func (app *DefaultGobootApp) Shutdown() {
	for _, shutdownFn := range app.shutdownFns{
		shutdownFn()
	}
}

func (app *DefaultGobootApp) RegisterShutdownFn(fn func()) {
	app.shutdownFns = append(app.shutdownFns, fn)
}